/**
 *Copyright (c) 2024 watereyes
 * safetymanagement is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.institution.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.koron.audit.approval.AfterApprovalService;
import com.koron.audit.domain.Audit;
import com.koron.audit.management.FlowManagement;
import com.koron.common.bean.StaffBean;
import com.koron.common.dfs.FastDFSClientWrapper;
import com.koron.common.domain.DataBean;
import com.koron.common.generator.DefaultIdGenerator;
import com.koron.institution.approval.ConformanceAssessmentAuditService;
import com.koron.institution.bean.*;
import com.koron.institution.mapper.*;
import com.koron.institution.service.api.ConformanceAssessmentService;
import com.koron.institution.uitls.BaseEntityUtil;
import com.koron.institution.uitls.BusinessCode;
import com.koron.institution.uitls.DateUtil;
import com.koron.institution.uitls.ExcelUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.koron.ebs.mybatis.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.swan.bean.MessageBean;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
@PropertySource("classpath:institution.properties")
public class ConformanceAssessmentServiceImpl implements ConformanceAssessmentService, InitializingBean, AfterApprovalService {

    private final static  Logger logger = LoggerFactory.getLogger(Logger.class);

    @Autowired
    private FlowManagement flowManagement;

//    @Value("${assessment_confirm}")
//    private String assessmentConfirm;

    @Autowired
    private FastDFSClientWrapper clientWrapper;

    MessageBean<InstitutionConformanceAssessmentCond> checkAndProduceAssessmentCond(String corpCode, String conformanceDescription, Integer page, Integer pageSize) {
        MessageBean<InstitutionConformanceAssessmentCond> msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(),
                InstitutionConformanceAssessmentCond.class);
        InstitutionConformanceAssessmentCond cond = new InstitutionConformanceAssessmentCond();
        if (page != null && page > 0 && pageSize != null && pageSize > 0) {
            cond.setPage(page);
            cond.setPageSize(pageSize);
            cond.setStart((page - 1) * pageSize);
        }

        if (StringUtils.isBlank(corpCode)) {
            msg.setCode(BusinessCode.EMPTY_ASSESSMENT_CORPCODE.getCode());
            msg.setDescription(BusinessCode.EMPTY_ASSESSMENT_CORPCODE.getDescription());
            return msg;
        } else {
            cond.setCorpCode(corpCode);
        }

        if (StringUtils.isNotBlank(conformanceDescription)) {
            cond.setConformanceDescription(conformanceDescription);
        }
        msg.setData(cond);
        return msg;
    }

    @Override
    public MessageBean<?> getAssessmentList(String corpCode, String reviseDescription, Integer page, Integer pageSize, StaffBean user) {
        MessageBean<DataBean> msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), DataBean.class);
        try (SessionFactory factory = new SessionFactory()) {
            InstitutionReviseAssessmentMapper mapper = factory.getMapper(InstitutionReviseAssessmentMapper.class);
            InstitutionConformanceAssessmentMapper conformanceAssessmentMapper = factory.getMapper(InstitutionConformanceAssessmentMapper.class);

            //判断集团用户还是司级用户
            MessageBean<InstitutionConformanceAssessmentCond> messageBean = checkAndProduceAssessmentCond(corpCode, reviseDescription, page, pageSize);
            if (messageBean.getCode() != 0) {
                return messageBean;
            }
            InstitutionConformanceAssessmentCond cond = messageBean.getData();
            List<InstitutionConformanceAssessment> list = conformanceAssessmentMapper.getListByCond(cond);
            int total = conformanceAssessmentMapper.getTotalByCond(cond);
            DataBean<InstitutionConformanceAssessment> dataBean = new DataBean<>();
            dataBean.setList(list);
            dataBean.setTotalNumber(total);
            dataBean.setPageNo(cond.getPage());
            dataBean.setPageSize(cond.getPageSize());
            dataBean.setTotalPage((pageSize == null || pageSize == 0) ? 0 : total / pageSize);
            msg.setData(dataBean);
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription(BusinessCode.FAILURE.getDescription());
            return msg;
        }
        return msg;
    }

    MessageBean<?> checkInstitutionConformanceAssessment(InstitutionConformanceAssessment assessment, MessageBean<?> msg) {
        if (assessment == null) {
            msg.setCode(BusinessCode.EMPTY_ASSESSMENT.getCode());
            msg.setDescription(BusinessCode.EMPTY_ASSESSMENT.getDescription());
            return msg;
        }
        if (StringUtils.isBlank(assessment.getConformanceDescription())) {
            msg.setCode(BusinessCode.EMPTY_ASSESSMENT_CONFORMANCE_DESCRIPTION.getCode());
            msg.setDescription(BusinessCode.EMPTY_ASSESSMENT_CONFORMANCE_DESCRIPTION.getDescription());
            return msg;
        }
        if (StringUtils.isBlank(assessment.getConformanceReason())) {
            msg.setCode(BusinessCode.EMPTY_ASSESSMENT_CONFORMANCE_REASON.getCode());
            msg.setDescription(BusinessCode.EMPTY_ASSESSMENT_CONFORMANCE_REASON.getDescription());
            return msg;
        }
        if (StringUtils.isBlank(assessment.getVersion())) {
            msg.setCode(BusinessCode.EMPTY_ASSESSMENT_VERSION.getCode());
            msg.setDescription(BusinessCode.EMPTY_ASSESSMENT_VERSION.getDescription());
            return msg;
        }
        if (assessment.getFileDate() == null) {
            msg.setCode(BusinessCode.EMPTY_ASSESSMENT_FILEDATE.getCode());
            msg.setDescription(BusinessCode.EMPTY_ASSESSMENT_FILEDATE.getDescription());
            return msg;
        }
        if (StringUtils.isBlank(assessment.getFileName())) {
            msg.setCode(BusinessCode.EMPTY_ASSESSMENT_FILENAME.getCode());
            msg.setDescription(BusinessCode.EMPTY_ASSESSMENT_FILENAME.getDescription());
            return msg;
        }
        if (StringUtils.isBlank(assessment.getCorpCode())) {
            msg.setCode(BusinessCode.EMPTY_ASSESSMENT_CORPCODE.getCode());
            msg.setDescription(BusinessCode.EMPTY_ASSESSMENT_CORPCODE.getDescription());
            return msg;
        }
        return msg;
    }

    InstitutionConformanceAssessmentItem parseRow(XSSFRow row, StaffBean user, InstitutionConformanceAssessment institutionConformanceAssessment,
                                                  Integer institutionType, InstitutionFileMapper fileMapper) {
        InstitutionConformanceAssessmentItem item = new InstitutionConformanceAssessmentItem();
        try {
            String fileName = ExcelUtil.getCellValue(row.getCell(1));
            String conformance = ExcelUtil.getCellValue(row.getCell(5));
            Integer conformanceFlag = null;
            if ("遵守符合".equals(conformance)) {
                conformanceFlag = 0;
            } else {
                conformanceFlag = 1;
            }
            String corpCode = institutionConformanceAssessment.getCorpCode();
            InstitutionFile fileCond = new InstitutionFile();
            fileCond.setInstitutionType(institutionType);
            fileCond.setFileName(fileName);
            fileCond.setCorpCode(corpCode);
            InstitutionFile institutionFile = fileMapper.getInstitutionByFileName(fileCond);
            if (institutionFile != null) {
                item.setConformanceAssessmentId(institutionConformanceAssessment.getId());
                item.setCorpCode(corpCode);
                item.setInstitutionId(institutionFile.getId());
                item.setInstitutionCode(institutionFile.getCode());
                item.setInstitutionFileCode(institutionFile.getFileCode());
                item.setInstitutionFileName(institutionFile.getFileName());
                item.setPublicationDate(institutionFile.getPublicationDate());
                item.setExecutionDate(institutionFile.getExecutionDate());
                item.setApplicableProvisions(institutionFile.getApplicableProvisions());
                item.setRemark(institutionFile.getRemark());
                item.setVersion(institutionFile.getVersion());
                item.setAttachment(institutionFile.getAttachment());
                item.setConformanceFlag(conformanceFlag);
                BaseEntityUtil.setAddBaseProperties(item, user);
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return null;
        }
        return item;
    }


    @Override
    public MessageBean<?> saveOrCommit(StaffBean user, InstitutionConformanceAssessment institutionConformanceAssessment, Integer operationType, String keepFileAddress, MultipartFile[] files, String approverCodeListStr) {
        MessageBean<?> msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), Object.class);
        SessionFactory factory = new SessionFactory();
        try {
            List<String> approverCodeList = null;
            InstitutionConformanceAssessmentMapper mapper = factory.getMapper(InstitutionConformanceAssessmentMapper.class);
            InstitutionFileMapper fileMapper = factory.getMapper(InstitutionFileMapper.class);
            boolean isAdd = false;
            if (StringUtils.isBlank(institutionConformanceAssessment.getId())) {
                isAdd = true;
                BaseEntityUtil.setAddBaseProperties(institutionConformanceAssessment, user);
            } else {
                InstitutionConformanceAssessment assessment = mapper.selectByPrimaryKey(institutionConformanceAssessment.getId());
                if (assessment == null) {
                    msg.setCode(BusinessCode.CONFORMANCE_ASSESSMENT_NOT_EXIST.getCode());
                    msg.setDescription(BusinessCode.CONFORMANCE_ASSESSMENT_NOT_EXIST.getDescription());
                    factory.close();
                    return msg;
                }
            }
            String[] keepAddressArray = StringUtils.isEmpty(keepFileAddress) ? null : keepFileAddress.split("[,，]");
            List<String> keepAddressList = new ArrayList<>();
            if (keepAddressArray != null && keepAddressArray.length > 0) {
                keepAddressList = Arrays.asList(keepAddressArray).stream().collect(Collectors.toList());
            }
            if (null == operationType) {
                msg.setCode(BusinessCode.ASSESSMENT__EMPTY_OPERATIONTYPE.getCode());
                msg.setDescription(BusinessCode.ASSESSMENT__EMPTY_OPERATIONTYPE.getDescription());
                factory.close();
                return msg;
            }
            if (1 != operationType && 0 != operationType) {
                msg.setCode(BusinessCode.ASSESSMENT_ILEAGEL_OPERATIONTYPE.getCode());
                msg.setDescription(BusinessCode.ASSESSMENT_ILEAGEL_OPERATIONTYPE.getDescription());
                factory.close();
                return msg;
            }
            //校验
            checkInstitutionConformanceAssessment(institutionConformanceAssessment, msg);
            if (msg.getCode() != 0) {
                factory.close();
                return msg;
            }
            //上传文件
            if (null != files) {
                if (files.length > 1) {
                    msg.setCode(BusinessCode.REQUEST_ONE_ASSESSMENT_FILE.getCode());
                    msg.setDescription(BusinessCode.REQUEST_ONE_ASSESSMENT_FILE.getDescription());
                    factory.close();
                    return msg;
                }
                for (MultipartFile file : files) {
                    String url = clientWrapper.uploadFile(file);
                    String filpath = url + "#" + file.getOriginalFilename();
                    keepAddressList.add(filpath);
                    //处理excel中的内容
                    InputStream inputStream = file.getInputStream();
                    XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
                    if (null == workbook) {
                        logger.error("上传文件为空");
                        msg.setCode(22001);
                        msg.setDescription("上传文件为空");
                        return msg;
                    }
                    XSSFSheet sheet = workbook.getSheetAt(0);
                    if (sheet == null) {
                        logger.error("上传文件为空");
                        msg.setCode(22001);
                        msg.setDescription("上传文件为空");
                        return msg;
                    }
                    int rowsNumm = sheet.getPhysicalNumberOfRows();
                    List<InstitutionConformanceAssessmentItem> conformanceAssessmentItemList = new ArrayList<>();
                    Integer institutionType = 1;
                    for (int i = 3; i < rowsNumm;i++ ) {
                        XSSFRow row = sheet.getRow(i);
                        InstitutionConformanceAssessmentItem item = parseRow(row, user, institutionConformanceAssessment, institutionType, fileMapper);
                        if (item != null) {
                            conformanceAssessmentItemList.add(item);
                        }
                    }
                    //删除之前的item
                    InstitutionConformanceAssessmentItemMapper conformanceAssessmentItemMapper = factory.getMapper(InstitutionConformanceAssessmentItemMapper.class);
                    if (!isAdd) {
                        conformanceAssessmentItemMapper.deleteByConformanceAssessmentId(institutionConformanceAssessment.getId());
                    }
                    //保存新的item
                    if (conformanceAssessmentItemList != null && !conformanceAssessmentItemList.isEmpty()) {
                        conformanceAssessmentItemMapper.insertList(conformanceAssessmentItemList);
                    } else {
                        msg.setCode(BusinessCode.EMPTY_ASSESSMENT_FILE_ITEM.getCode());
                        msg.setDescription(BusinessCode.EMPTY_ASSESSMENT_FILE_ITEM.getDescription());
                        factory.close(false);
                        return msg;
                    }
                }
            }
            if (keepAddressList == null || keepAddressList.isEmpty()) {
                msg.setCode(BusinessCode.EMPTY_ASSESSMENT_FILE.getCode());
                msg.setDescription(BusinessCode.EMPTY_ASSESSMENT_FILE.getDescription());
                factory.close();
                return msg;
            }
            institutionConformanceAssessment.setAttachment((keepAddressList == null || keepAddressList.size() <= 0) ? null : new Gson().toJson(keepAddressList));
            Audit audit = null;
            if (operationType == 0) {
                //保存草稿
                institutionConformanceAssessment.setState(0);
            } else {
                if (StringUtils.isBlank(approverCodeListStr)) {
                    msg.setCode(BusinessCode.EMPTY_INSTITUTION_APPROVER.getCode());
                    msg.setDescription(BusinessCode.EMPTY_INSTITUTION_APPROVER.getDescription());
                    return msg;
                }
                approverCodeList = JSONObject.parseArray(approverCodeListStr, String.class);
                if (approverCodeList == null || approverCodeList.isEmpty()) {
                    msg.setCode(BusinessCode.EMPTY_INSTITUTION_APPROVER.getCode());
                    msg.setDescription(BusinessCode.EMPTY_INSTITUTION_APPROVER.getDescription());
                    return msg;
                }
                //提交审批
                institutionConformanceAssessment.setState(1);
                // 构造audit
                audit = new Audit();
                Date now = new Date();
                audit.setId(DefaultIdGenerator.getInstance().generateLongId());
                audit.setUpdateUser(user.getName());
                audit.setUpdateTime(now);
                audit.setAddUser(user.getName());
                audit.setAddTime(now);
                audit.setFlowType(1);
                audit.setOperation(1);
                audit.setTarget(ConformanceAssessmentAuditService.class.getName());
                audit.setFlowName("合规评价待审批");
                audit.setTitle("合规评价待审批");
                audit.setCorpCode(institutionConformanceAssessment.getCorpCode());
                audit.setInitiatorCode(user.getCode());
                audit.setDescription("合规评价提交审批");
                audit.setState(1);
//                audit.setTemplateKey(assessmentConfirm);
            }

            //判断是否新增
            if (isAdd) {
                //新增
//                BaseEntityUtil.setAddBaseProperties(institutionReviseAssessment, user);
                mapper.insert(institutionConformanceAssessment);
            } else {
                //修改

                BaseEntityUtil.setUpdateBaseProperties(institutionConformanceAssessment, user);
                mapper.updateByPrimaryKeySelective(institutionConformanceAssessment);
            }
            if (audit != null) {
                List<String> idList = new ArrayList<>();
                idList.add(institutionConformanceAssessment.getId());
                audit.setBusinessIds(new Gson().toJson(idList));
                Map<String, Object> businessMap = new HashMap<>();
                StringBuilder codes = new StringBuilder();
                for (String code : approverCodeList) {
                    codes.append("1-").append(code.split("_")[0]).append(",");
                }
                businessMap.put("approver", codes.toString().substring(0, codes.lastIndexOf(",")));
                if (!flowManagement.initFlow(user, audit, businessMap)) {
                    factory.close(false);
                    msg.setCode(BusinessCode.FAILURE.getCode());
                    msg.setDescription("提交评审修订失败");
                } else {
                    try {
                        institutionConformanceAssessment.setFlowInstanceId(audit.getFlowInstanceId());
                        mapper.updateByPrimaryKeySelective(institutionConformanceAssessment);
                    } catch (Exception e) {
                        logger.error("审批流程实例id保存失败!--------" + audit.getId());
                    }
                    factory.close();
                    msg.setCode(BusinessCode.SUCCESS.getCode());
                    msg.setDescription("提交评审修订成功");
                }
            } else {
                factory.close();
            }
        } catch (Exception e) {
            factory.close(false);
            logger.error(e.getMessage(),e);
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription(BusinessCode.FAILURE.getDescription());
            return msg;
        }finally {
            if (null != factory){
                factory.close();
            }
        }
        return msg;
    }

    @Override
    public Map<String, Object> queryInstitution(String startDateStr, String endDateStr, String corpCode, String corpName, Integer institutionType, StaffBean user) {
        Map<String, Object> map = new HashMap<>();
        try (SessionFactory factory = new SessionFactory()) {
            InstitutionFileMapper mapper = factory.getMapper(InstitutionFileMapper.class);
            Date start = DateUtil.formatStringToDate(startDateStr, DateUtil.DATE_FORMAT_YMD);
            Date end = DateUtil.formatStringToDate(endDateStr, DateUtil.DATE_FORMAT_YMD);
            if (StringUtils.isBlank(corpCode)) {
                return null;
            }
            Map param = new HashMap();
            param.put("start", start);
            param.put("end", end);
            param.put("corpCode", corpCode);
            param.put("institutionType", 1);
            map.put("data", mapper.queryInstitution(param));
            map.put("corpName", corpName);
            map.put("userName", user == null ? "" : user.getName());
            map.put("makeDate", new Date());
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return null;
        }
        return map;
    }

    @Override
    public MessageBean<?> getProcessData(String ids) {
        MessageBean<List> msg = MessageBean.create(0, "success", List.class);
        try (SessionFactory factory = new SessionFactory();) {
            if (StringUtils.isNotBlank(ids)) {
                List<String> idList = JSONObject.parseArray(ids, String.class);
                if (idList != null && !idList.isEmpty()) {
                    InstitutionConformanceAssessmentMapper mapper = factory.getMapper(InstitutionConformanceAssessmentMapper.class);
                    List<InstitutionConformanceAssessment> list = mapper.queryListByIds(idList);
                    msg.setData(list);
                }else {
                    msg.setCode(BusinessCode.EMPTY_CONFORMANCE_ID.getCode());
                    msg.setDescription(BusinessCode.EMPTY_CONFORMANCE_ID.getDescription());
                    return msg;
                }
            } else {
                msg.setCode(BusinessCode.EMPTY_CONFORMANCE_ID.getCode());
                msg.setDescription(BusinessCode.EMPTY_CONFORMANCE_ID.getDescription());
                return msg;
            }
        } catch (Exception e) {
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription(BusinessCode.FAILURE.getDescription());
            return msg;
        }
        return msg;
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        Map map = flowManagement.getHandlers();
        map.put(ConformanceAssessmentAuditService.class.getName(), this);
    }

    @Override
    public void editApproval(Audit audit) {

    }

    @Override
    public void discardApproval(Audit audit) {

    }

    @Override
    public void processDiscard(Audit audit) {

    }


    @Override
    public void reject(Audit audit, List<String> userIdList) {
        // TODO 流程驳回操作
    }

    @Override
    public void passApproval(Integer operation, Audit audit) {
        // TODO 流程提交成功操作
    }
}
